2 Test without authentication

# test
url <- "https://api.octopus.energy/v1/products"
message("Getting: ", url)
## Getting: https://api.octopus.energy/v1/products
resp <- httr::GET(url)

message("Status code: ", resp$status_code)
## Status code: 200
df <- jsonlite::parse_json(resp, simplifyVector = TRUE)
## No encoding supplied: defaulting to UTF-8.
makeFlexTable(head(df$results), cap = "Example products list (first 6 rows)")

3 Tests with authentication

3.1 Basic info

url <- paste0("https://api.octopus.energy/v1/accounts/", apiParams$accountNo , "/")

resp <- httr::GET(url = url, authenticate(user = apiParams$key, password = ""))

df <- jsonlite::parse_json(resp, simplifyVector = TRUE)
## No encoding supplied: defaulting to UTF-8.
props <- data.table::as.data.table(df$properties)
makeFlexTable(head(props[, .(town, county, 
                             electricity_meter_points,gas_meter_points)]), cap = "Properties linked to this account (non-disclosive data)")

List the electricity meter points.

# this is a list of n mpans
length(props$electricity_meter_points)
## [1] 2
message("n MPANS listed: ", length(df$properties$electricity_meter_points))
## n MPANS listed: 2
for(n in 1:length(df$properties$electricity_meter_points)){
  print(props$electricity_meter_points[n])
}
## [[1]]
##            mpan profile_class consumption_standard
## 1 2000006198482             1                 7678
##                          meters
## 1 L78C64517, 01, STANDARD, TRUE
##                                                                                                                                                      agreements
## 1 E-1R-SUPER-GREEN-12M-20-09-22-H, E-1R-SUPER-GREEN-12M-20-09-22-H, 2020-11-01T00:00:00Z, 2020-11-21T00:00:00Z, 2020-11-01T00:00:00Z, 2021-06-30T00:00:00+01:00
##   is_export
## 1     FALSE
## 
## [[1]]
##            mpan profile_class consumption_standard
## 1 1050001805886             1                 3322
##                          meters
## 1 19L3027004, 1, STANDARD, TRUE
##                                                                                                                                                    agreements
## 1 E-1R-SUPER-GREEN-12M-20-09-22-A, E-1R-LOYAL-FIX-12M-21-10-07-A, 2021-07-01T00:00:00+01:00, 2021-11-21T00:00:00Z, 2021-11-21T00:00:00Z, 2022-11-21T00:00:00Z
##   is_export
## 1     FALSE
length(df$properties$gas_meter_points)
## [1] 2
message("n MPRNS listed: ", length(df$properties$gas_meter_points))
## n MPRNS listed: 2
for(n in 1:length(df$properties$gas_meter_points)){
  print(df$properties$gas_meter_points[n])
}
## [[1]]
##         mprn consumption_standard         meters
## 1 4256845702                19018 G4A01559730801
##                                                                                                                                                      agreements
## 1 G-1R-SUPER-GREEN-12M-20-09-22-H, G-1R-SUPER-GREEN-12M-20-09-22-H, 2020-11-01T00:00:00Z, 2020-11-21T00:00:00Z, 2020-11-01T00:00:00Z, 2021-06-30T00:00:00+01:00
## 
## [[1]]
##         mprn consumption_standard                                       meters
## 1 7825700304                15129 E6S12725512161, E6S17944211961, NOTINSTALLED
##                                                                            agreements
## 1 G-1R-LOYAL-FIX-12M-21-10-07-A, 2021-10-04T00:00:00+01:00, 2022-10-04T00:00:00+01:00

3.2 Electricity

3.2.1 Consumption

See: https://www.guylipman.com/octopus/api_guide.html#s3

url <- paste0("https://api.octopus.energy/v1/electricity-meter-points/", 
              apiParams$elec_import_mpan , "/",
              "meters/",
              apiParams$elec_import_serial, "/",
              "consumption/",
              "?period_from=2022-01-01T00:00Z",
              "&page_size=10000")
# get data via httr ----
resp <- httr::GET(url = url, authenticate(user = apiParams$key, password = ""))
df <- jsonlite::parse_json(resp, simplifyVector = TRUE) # creates a df of which 'results' = the data
## No encoding supplied: defaulting to UTF-8.
elecCons_dt <- data.table::as.data.table(df$results) # convert to dt

# derived variables ----
elecCons_dt <- makeDerivedVars(elecCons_dt)

maxTime <- max(elecCons_dt$dv_start)

hoursAgo <- now() - maxTime

# meter is SMETS2
elecCons_dt[, consumption_kWh := consumption] # for clarity - see https://developer.octopus.energy/docs/api/#list-consumption-for-a-meter

The data used here is up to 2022-06-15 23:30:00, which is 17.3 hours ago. In general the Octopus API seems to have data up to midnight last night.

t <- elecCons_dt[, .(nDays = uniqueN(dv_date),
                     sumkWh = sum(consumption_kWh),
                     halfHourly_meankWh = mean(consumption_kWh)),
                 keyby = .(month = lubridate::month(dv_date))]

makeFlexTable(t, cap = "Monthly stats")
message("Total elec to date")
## Total elec to date
sum(t$sumkWh)
## [1] 1759.268
t <- elecCons_dt[, .(nDays = uniqueN(dv_date),
                     sumkWh = sum(consumption_kWh)),
                 keyby = .(dv_date)]
message("Projected elec annual total")
## Projected elec annual total
mean(t$sumkWh)*365
## [1] 3868.27

Figure 3.1 shows half-hourly electricity import (‘consumption’) for the current year. Spot the power cuts…

To do: mark weekends somehow

ggplot2::ggplot(elecCons_dt, aes(x = dv_date, y = dv_hms, fill = consumption_kWh)) +
  geom_tile() +
  theme(legend.position = "bottom") +
  scale_fill_viridis_c(name = "Electricity import (kWh)") +
  labs(x = "Date",
       y = "Half-hour")
Half hourly electricity import (current year)

Figure 3.1: Half hourly electricity import (current year)

Repeat but with just the last 7 days of data - useful for checking recent appliance use and offspring effects.

today <- lubridate::today()
p <- ggplot2::ggplot(elecCons_dt[dv_date >= today - 7], aes(x = dv_date, y = dv_hms, fill = consumption_kWh)) +
  geom_tile() +
  theme(legend.position = "bottom") +
  scale_fill_viridis_c(name = "Electricity import (kWh)") +
  labs(x = "Date",
       y = "Half-hour")

plotly::ggplotly(p)

Figure 3.2: Half hourly electricity import (current year, last 7 days)

plotDT <- elecCons_dt[, .(sum_kWh = sum(consumption_kWh),
                 mean_kWh = mean(consumption_kWh),
                 nObs = .N), keyby = .(dv_date, dv_weekend)]

ggplot2::ggplot(plotDT, aes(x = dv_date, y = mean_kWh, 
                            colour = dv_weekend)) +
  geom_point() +
  geom_smooth() +
  #facet_grid(dv_peakPeriod ~ .) +
  scale_colour_viridis_d(name = "Weekend") +
  labs(x = "Date",
       y = "Mean kWh")
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
Daily electricity import (current year)

Figure 3.3: Daily electricity import (current year)

Figure 3.4 shows the mean daily kWh import with a smoothed curve for each period as defined below.

Early morning is effectively our baseload.

# check periods
t <- elecCons_dt[, .(min = min(dv_hms),
                max = max(dv_hms)),
            keyby = .(dv_peakPeriod)]

t
##    dv_peakPeriod      min      max
## 1: Early morning 00:00:00 06:30:00
## 2:  Morning peak 07:00:00 08:30:00
## 3:      Day time 09:00:00 15:30:00
## 4:  Evening peak 16:00:00 19:30:00
## 5:  Late evening 20:00:00 23:30:00
plotDT <- elecCons_dt[, .(sum_kWh = sum(consumption_kWh),
                 mean_kWh = mean(consumption_kWh),
                 nObs = .N), keyby = .(dv_date, dv_peakPeriod, dv_weekend)]

ggplot2::ggplot(plotDT, aes(x = dv_date, y = mean_kWh, 
                            colour = dv_peakPeriod)) +
  geom_line() +
  geom_smooth() +
  #facet_grid(dv_peakPeriod ~ .) +
  theme(legend.position = "bottom") +
  guides(colour = guide_legend (ncol = 3)) +
  scale_colour_viridis_d(name = "Peak period") +
  labs(x = "Date",
       y = "Mean kWh per period")
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
Daily electricity import by peak period (current year)

Figure 3.4: Daily electricity import by peak period (current year)

3.2.2 Export

This will be a new MPAN but specified as export - although the url will still say consumption. We do not have this even though the PV is exporting on (some) days.

It may be that we only get this data if we sign up for the export tariff.

See https://www.guylipman.com/octopus/api_guide.html#s3

3.3 Gas Consumption

We need to convert the gas consumption from m3 to kWh - see https://developer.octopus.energy/docs/api/#list-consumption-for-a-meter

gasM3TokWh <- 11.36

We use 11.36 (https://www.theenergyshop.com/guides/how-to-convert-gas-units-to-kwh)

url <- paste0("https://api.octopus.energy/v1/gas-meter-points/", 
              apiParams$gas_mpan , "/",
              "meters/",
              apiParams$gas_serial, "/",
              "consumption",
              "?period_from=2022-01-01T00:00Z",
              "&page_size=10000")
resp <- httr::GET(url = url, authenticate(user = apiParams$key, password = ""))
df <- jsonlite::parse_json(resp, simplifyVector = TRUE)
## No encoding supplied: defaulting to UTF-8.
gasCons_dt <- data.table::as.data.table(df$results)
gasCons_dt <- makeDerivedVars(gasCons_dt)

# gas 'consumption' is m3 - https://developer.octopus.energy/docs/api/#list-consumption-for-a-meter
# convert to kWh
gasCons_dt[, consumption_m3 := consumption]
gasCons_dt[, consumption_kWh := consumption * gasM3TokWh]

Note that this data starts later as we finally got the original un-registered smart meter replaced in February.

t <- gasCons_dt[, .(nDays = uniqueN(dv_date),
                     sumkWh = sum(consumption_kWh),
                     halfHourly_meankWh = mean(consumption_kWh)),
                 keyby = .(month = lubridate::month(dv_date))]

makeFlexTable(t, cap = "Monthly stats")
message("Total gas to date")
## Total gas to date
sum(t$sumkWh)
## [1] 6781.409
t <- gasCons_dt[, .(nDays = uniqueN(dv_date),
                     sumkWh = sum(consumption_kWh)),
                 keyby = .(dv_date)]
message("Projected gas annual total")
## Projected gas annual total
mean(t$sumkWh)*365
## [1] 19801.71

Figure 3.5 shows half-hourly gas import (‘consumption’) for the current year. The power cuts are even easier to see here. Interestingly the pattern after the gas boiler was serviced in June is more varied. What did he change?

ggplot2::ggplot(gasCons_dt, aes(x = dv_date, y = dv_hms, fill = consumption_kWh)) +
  geom_tile() +
  theme(legend.position = "bottom") +
  scale_fill_viridis_c(name = "Gas import (kWh)") +
  labs(x = "Date",
       y = "Half-hour")
Half-hourly gas consumption (current year)

Figure 3.5: Half-hourly gas consumption (current year)

Repeat but with just the last 7 days of data - useful for checking recent appliance use and offspring effects.

today <- lubridate::today()
p <- ggplot2::ggplot(gasCons_dt[dv_date >= today - 7], aes(x = dv_date, y = dv_hms, fill = consumption_kWh)) +
  geom_tile() +
  theme(legend.position = "bottom") +
  scale_fill_viridis_c(name = "Gas import (kWh)") +
  labs(x = "Date",
       y = "Half-hour")

plotly::ggplotly(p)

Figure 3.6: Half hourly gas import (current year, last 7 days)

Figure ?? shows the mean daily kWh import with a smoothed curve.

To do: mark weekends etc

plotDT <- gasCons_dt[, .(sum_kWh = sum(consumption_kWh),
                 mean_kWh = mean(consumption_kWh),
                 nObs = .N), keyby = .(dv_date, dv_weekend)]

ggplot2::ggplot(plotDT, aes(x = dv_date, y = sum_kWh, 
                            colour = dv_weekend)) +
  geom_point() +
  geom_smooth() +
  theme(legend.position = "bottom") +
  guides(colour = guide_legend (ncol = 3)) +
  scale_colour_viridis_d(name = "Weekend") +
  labs(x = "Date",
       y = "Sum kWh per day")
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
Daily gas consumption (current year)

Figure 3.7: Daily gas consumption (current year)

ggplot2::ggplot(plotDT, aes(x = dv_date, y = mean_kWh, 
                            colour = dv_weekend)) +
  geom_point() +
  geom_smooth() +
  theme(legend.position = "bottom") +
  guides(colour = guide_legend (ncol = 3)) +
  scale_colour_viridis_d(name = "Weekend") +
  labs(x = "Date",
       y = "Mean kWh per day")
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
Daily gas consumption (current year)

Figure 3.8: Daily gas consumption (current year)

Figure 3.9 shows the mean daily kWh import with a smoothed curve by period of the day.

To do: mark weekends etc

plotDT <- gasCons_dt[, .(sum_kWh = sum(consumption_kWh),
                 mean_kWh = mean(consumption_kWh),
                 nObs = .N), keyby = .(dv_date, dv_peakPeriod, dv_weekend)]

ggplot2::ggplot(plotDT, aes(x = dv_date, y = mean_kWh, 
                            colour = dv_peakPeriod)) +
  geom_line() +
  geom_smooth() +
  #facet_grid(dv_peakPeriod ~ .) +
  theme(legend.position = "bottom") +
  guides(colour = guide_legend (ncol = 3)) +
  scale_colour_viridis_d(name = "Peak period") +
  labs(x = "Date",
       y = "Mean kWh per period")
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
Daily gas consumption by peak period (current year)

Figure 3.9: Daily gas consumption by peak period (current year)

4 Annexes

4.1 Data descriptions

4.1.1 Electricity consumption

Use skmir::skim()to summarise.

skimr::skim(elecCons_dt)
Table 4.1: Data summary
Name elecCons_dt
Number of rows 7968
Number of columns 9
Key NULL
_______________________
Column type frequency:
character 3
Date 1
difftime 1
factor 1
numeric 2
POSIXct 1
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
interval_start 0 1 20 25 0 7968 0
interval_end 0 1 20 25 0 7968 0
dv_weekend 0 1 6 8 0 3 0

Variable type: Date

skim_variable n_missing complete_rate min max median n_unique
dv_date 0 1 2022-01-01 2022-06-15 2022-03-24 166

Variable type: difftime

skim_variable n_missing complete_rate min max median n_unique
dv_hms 0 1 0 secs 84600 secs 42300 secs 48

Variable type: factor

skim_variable n_missing complete_rate ordered n_unique top_counts
dv_peakPeriod 0 1 FALSE 5 Ear: 2324, Day: 2324, Eve: 1328, Lat: 1328

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
consumption 0 1 0.22 0.22 0 0.09 0.14 0.28 1.97 ▇▁▁▁▁
consumption_kWh 0 1 0.22 0.22 0 0.09 0.14 0.28 1.97 ▇▁▁▁▁

Variable type: POSIXct

skim_variable n_missing complete_rate min max median n_unique
dv_start 0 1 2022-01-01 2022-06-15 23:30:00 2022-03-24 23:45:00 7968

4.1.2 Gas consumption

Use skmir::skim()to summarise.

skimr::skim(gasCons_dt)
Table 4.2: Data summary
Name gasCons_dt
Number of rows 5927
Number of columns 10
Key NULL
_______________________
Column type frequency:
character 3
Date 1
difftime 1
factor 1
numeric 3
POSIXct 1
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
interval_start 0 1 20 25 0 5927 0
interval_end 0 1 20 25 0 5927 0
dv_weekend 0 1 6 8 0 3 0

Variable type: Date

skim_variable n_missing complete_rate min max median n_unique
dv_date 0 1 2022-02-11 2022-06-15 2022-04-15 125

Variable type: difftime

skim_variable n_missing complete_rate min max median n_unique
dv_hms 0 1 0 secs 84600 secs 12:00:00 48

Variable type: factor

skim_variable n_missing complete_rate ordered n_unique top_counts
dv_peakPeriod 0 1 FALSE 5 Day: 1730, Ear: 1722, Eve: 992, Lat: 991

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
consumption 0 1 0.10 0.14 0 0 0.02 0.16 1.19 ▇▁▁▁▁
consumption_m3 0 1 0.10 0.14 0 0 0.02 0.16 1.19 ▇▁▁▁▁
consumption_kWh 0 1 1.14 1.54 0 0 0.25 1.82 13.53 ▇▁▁▁▁

Variable type: POSIXct

skim_variable n_missing complete_rate min max median n_unique
dv_start 0 1 2022-02-11 12:00:00 2022-06-15 23:00:00 2022-04-15 05:30:00 5927

5 References